﻿using System;
using System.IO;
using ICSharpCode.SharpZipLib;
using System.Text;

namespace SilverlightDatabase.Compression
{
    /// <summary>
    /// Utility that peerfomrs compression and decompression
    /// Please see License aggremen t with CSharpZipLib on CodePlex:
    /// http://slsharpziplib.codeplex.com/license
    /// 
    /// </summary>
    public static class CompressionUtility
    {
        /// <summary>
        /// Compress string
        /// </summary>
        /// <param name="input">String to compress</param>
        /// <returns>Byte array containing compressed string</returns>
        public static byte[] CompressString(string input)
        {
            return Compress(ConvertStringToBytes(input));
        }

        /// <summary>
        /// Decompress byte array and convert to string
        /// </summary>
        /// <param name="byteInput">Byte to decompress</param>
        /// <returns>String</returns>
        public static string DecompressToString(byte[] byteInput)
        {
            return ConvertBytesToString(Decompress(byteInput));
        }

        /// <summary>
        /// Compress byte array
        /// </summary>
        /// <param name="byteData">Input array</param>
        /// <returns>Compressed byte array</returns>
        public static byte[] Compress(byte[] byteData)
        {
            MemoryStream ms = new MemoryStream();
            ICSharpCode.SharpZipLib.Zip.Compression.Deflater defl =
               new ICSharpCode.SharpZipLib.Zip.Compression.Deflater(9, false);
            Stream s =
                new ICSharpCode.SharpZipLib.Zip.Compression.Streams.DeflaterOutputStream(ms, defl);
            s.Write(byteData, 0, byteData.Length);
            s.Close();
            byte[] compressedData = (byte[])ms.ToArray();
            return compressedData;
        }

        /// <summary>
        /// Decompress byte array
        /// </summary>
        /// <param name="byteInput">Array to decompress</param>
        /// <returns>Decompressed array</returns>
        public static byte[] Decompress(byte[] byteInput)
        {
            MemoryStream ms = new MemoryStream(byteInput, 0, byteInput.Length);
            byte[] bytResult = null;
            Stream s2 =
               new ICSharpCode.SharpZipLib.Zip.Compression.Streams.InflaterInputStream(ms);

            bytResult = ReadFullStream(s2);
            s2.Close();
            return bytResult;
        }

        /// <summary>
        /// Read entire stream into a byte array
        /// </summary>
        /// <param name="stream">Stream to read</param>
        /// <returns>Byte array</returns>
        public static byte[] ReadFullStream(Stream stream)
        {
            byte[] buffer = new byte[32768];
            using (MemoryStream ms = new MemoryStream())
            {
                while (true)
                {
                    int read = stream.Read(buffer, 0, buffer.Length);
                    if (read <= 0)
                        return ms.ToArray();
                    ms.Write(buffer, 0, read);
                }
            }
        }

        /// <summary>
        /// Convert a string into an array of bytes
        /// </summary>
        /// <param name="input">String to convert</param>
        /// <returns>Byte atray that repsesents the string</returns>
        public static byte[] ConvertStringToBytes(string input)
        {
            MemoryStream stream = new MemoryStream();
            using (StreamWriter writer = new StreamWriter(stream))
            {
                writer.Write(input);
                writer.Flush();
            }
            return stream.ToArray();
        }

        /// <summary>
        /// Convert abyte array into a string
        /// </summary>
        /// <param name="bytes">Byte array to convert</param>
        /// <returns>String constructed from bytes</returns>
        public static string ConvertBytesToString(byte[] bytes)
        {
            string output = String.Empty;
            MemoryStream stream = new MemoryStream(bytes);
            stream.Position = 0;
            using (StreamReader reader = new StreamReader(stream))
            {
                output = reader.ReadToEnd();
            }
            return output;
        }

    }
}
